Building an xdg-app – part 2

Welcome back to this multi-part tutorial in how to create xdg-app applications. In part 1 we installed everything we needed and manually created our first application. In this part we will build a more complex application, using the basic xdg-app tools.

I chose to build the gnome dictionary application, because its a small app with no dependencies. To build it we use the SDK (software development kit) that matches the runtime we used in the previous part. The SDK contains the development toolchain and the headers needed to build applications using the libraries in the runtime.

First we need to install the SDK. This is rather large, so it may take a while:

xdg-app --user install gnome org.gnome.Sdk 3.20

We also want the sources to the application we want to build:

wget https://download.gnome.org/sources/gnome-dictionary/3.20/gnome-dictionary-3.20.0.tar.xz

Just like last time we start by creating the application directory where the application will be installed. However, this time we use the build-init command to create it:

xdg-app build-init appdir2 org.gnome.Dictionary org.gnome.Sdk org.gnome.Platform 3.20

This creates a directory called “appdir2” with a metadata file and the right directory structure. The only difference from last time is that the metadata file specifies a sdk as well as a runtime. A sdk is really just a runtime, but it is used during the build phase, rather than when the user runs the app.

Now that we have specified a sdk we can use the xdg-app build command. This is very similar to the run command, except it operates on an application build directory rather than an installed application, and it uses the sdk instead of the regular runtime. It also gives the sandbox access to all your files. For example, you can run:

$ xdg-app build appdir2 touch /app/some_file
$ xdg-app build appdir2 ls -l /app
total 0
-rw-r--r-- 1 alex wheel 0 Feb 19 16:03 some_file

This will have created a file “appdir2/files/some_file” in your tutorial directory.

Using this command you can build the application like you normally would, except in a sandbox. Since it is in a sandbox it will automatically use the compiler and other tools from the sdk. gnome-dictionary builds fine with a traditional configure; make; make install; incantation, so we only have to add a xdg-app prefix to these:

tar xvf gnome-dictionary-3.20.0.tar.xz
cd gnome-dictionary-3.20.0/
xdg-app build ../appdir2 ./configure --prefix=/app
xdg-app build ../appdir2 make
xdg-app build ../appdir2 make install
cd ..

We also need to give the app access to X11 and the network, and specify the command that is used to start the app. This is done with the build-finish operation:

xdg-app build-finish appdir2 --socket=x11 --share=network --command=gnome-dictionary

This adds some extra info to the metadata file, and creates the exports directory, which we’ll come back to later. You can install and try the app by running

xdg-app build-export repo appdir2
xdg-app --user install tutorial-repo org.gnome.Dictionary
xdg-app run org.gnome.Dictionary

You will see some warnings because we didn’t grant the app access to the dconf database, but other than that everything works.

On interesting new thing here is the exports mentioned above. If you look into the appdir2/export/ directory you will find this structure:

appdir2/export
└── share
    ├── applications
    │   └── org.gnome.Dictionary.desktop
    └── dbus-1
        └── services
            └── org.gnome.Dictionary.service

And when the app is installed, these files will be exported into ~/.local/share/xdg-app/exports/. The xdg-app package then sets the XDG_DATA_DIRS environment variable to point to this directory, which means your desktop environment will look in it. This sounds a bit complicated, but what it means is that once the app is installed it will automatically appear among the normal applications in your desktop environment.

There is one limit on what gets exported though. All the filesnames (not directory names) must have the application id as a prefix. This works in the above setup because the desktop file is org.gnome.Dictionary.desktop, which is what we used for the id. This limitation guarantees that applications cannot cause conflicts, and that they can’t override any system installed applications.

We have now built a simple application with no dependencies. If there are any dependencies that are not in the runtime you need to build those too. This means more cycles of configure; make; make install; While this is not hard, it is a lot of manual repeated work. In the next part of this series we will see how this can be automated using the xdg-app-builder tool.

Building an xdg-app – part 1

Welcome to part 1 in this multi-part tutorial in how to create xdg-app applications.

First of all you need to install xdg-app. Fedora 23 ships with xdg-app packages, but some distributions do not. I have made this page with packages that you can use.

This tutorial is using xdg-app 0.4.12, which is the latest version. Older versions should work too, but minor things may need to be changed in the commands, and not all features may be supported.

A fundamental concept in xdg-app is the runtime/application split. Every app depends on a runtime, which supplies the core libraries that the app relies on. Runtimes are typically shared by many applications, but a user can have multiple runtimes installed at the same time.

For this tutorial we will be using the gnome nightly build runtime. It is available in a xdg-app repostitory on sdk.gnome.org. If you tried the gnome nightly builds from my previous blog entry you will have these already, but otherwise you can get it by doing:

$ wget https://sdk.gnome.org/keys/gnome-sdk.gpg
$ xdg-app --user remote-add --gpg-key=gnome-sdk.gpg gnome http://sdk.gnome.org/repo
$ xdg-app --user install gnome org.gnome.Platform 3.20

Once it is installed you can also update it by doing:

xdg-app --user update org.gnome.Platform 3.20

Now we have all that we need to create a simple application. Lets start by writing an application. Put this in a file called “hello.sh”:

#!/bin/sh
echo "Hello world, from a sandbox"

Then we need some information about the application. In xdg-app this is in specified in a key-value file called “metadata”. For a simple app like this it doesn’t contain much, so we can create it manually:

[Application]
name=org.test.Hello
runtime=org.gnome.Platform/x86_64/3.20
command=hello.sh

This specifies the application identifier (org.test.Hello) as well as the runtime the application uses and the command to start the app with.

An xdg-app really doesn’t require more than this, although the application must have a special layout. Using these sources we can create an application directory “appdir” like this:

mkdir appdir
mkdir appdir/files
mkdir appdir/files/bin
mkdir appdir/export
cp metadata appdir/
cp hello.sh appdir/files/bin/
chmod a+x appdir/files/bin/hello.sh

In order for xdg-app to be able to install this application we need to put it in an  repository. This is done with the build-export command:

xdg-app build-export repo appdir

This will initialize a local repository in the directory “repo”  and export the app to it. We can test it using:

xdg-app --user remote-add --no-gpg-verify tutorial-repo repo
xdg-app --user install tutorial-repo org.test.Hello
xdg-app run org.test.Hello

This will print “Hello world, from a sandbox”, which means we just created, packaged, installed and ran our first xdg-app application!

If you want to examine the sandbox a bit you can use the –command=sh argument to xdg-app run, which will give you a shell inside the application sandbox where you can explore the sandbox. For example:

[alex@localhost ~]$ xdg-app run --command=sh org.test.Hello
sh-4.3$ ls -lR /app
/app:
total 0
drwxr-xr-x 1 alex wheel 16 jan 1 1970 bin
/app/bin:
total 4
-rwxr-xr-x 2 alex wheel 45 jan 1 1970 hello.sh
sh-4.3$ echo $PATH
/app/bin:/usr/bin
sh-4.3$ hello.sh
Hello world, from a sandbox
sh-4.3$ ls -la ~/
total 0
drwxr-xr-x 3 alex wheel 60 feb 19 16:11 .
drwxr-xr-x 3 alex wheel 60 feb 19 16:11 ..
drwxr-xr-x 3 alex wheel 60 feb 19 16:11 .var
sh-4.3$ ls ~/.var/app/org.test.Hello/
cache  config  data

Here we see that all the files from the application appears in /app, and PATH points to /app/bin which means you can easily run it. We also see that by default the application has no access to any files from the users home directory (it’s empty) other than the ~/.var/app/org.test.Hello directory where the app can store its own data. You can also explore /usr, which comes from the runtime.

This is a very manual approach to creating a xdg-app, in the next part of this tutorial we will look at how to use the “xdg-app build” command and an SDK to build applications.